#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Changelog
# 0.1 : initial release, Sherbrooke l14 only
# 0.1.1 : add timezone awareness
# 0.1.9 : database introduction
# 0.2 : index displays list of lines and custom link for each line
# 0.2.1: New UI
# 0.2.2: New UI and displays 6 next 
# 0.2.5: include pytzgae for ALL timezones
# 0.2.9: include a XMPP bot
# 0.3.0: New UI design with CSS3 buttons

import cgi
import os
import string

from datetime import datetime, date, time

from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.api import xmpp

from pytz.gae import pytz

class Line(db.Model):
    code = db.StringProperty()
    color = db.StringProperty()
    tz = db.StringProperty()
    network = db.StringProperty()
    line = db.StringProperty()
    stop = db.StringProperty()
    direction = db.StringProperty()
    week = db.StringListProperty()
    staurday = db.StringListProperty()
    sunday = db.StringListProperty()
    summer = db.StringListProperty()

def nextOneTime(when,time):
    return [x for x in when if x > time ][0]

def nextOne(when,tzwhen):
    timeNow = datetime.now(tz=pytz.timezone(tzwhen))
    return nextOneTime(when,timeNow.strftime("%H%M"))        

def timePeriod(bus):
    timeNow = datetime.now(tz=pytz.timezone(bus.tz))
    month = timeNow.strftime("%m")
    day = timeNow.strftime("%w")
    if day == 0 :
        return bus.sunday
    elif day == 6 :
        return bus.saturday
    elif month in ["07","08"] :
        return bus.summer
    else :
        return bus.week

def prettyPrintTime(x) :
    return (len(x)==4) and x[:2]+':'+x[2:] or "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"

def listCombine(l1,l2):
    l1.reverse()
    l = []
    for i in l1 :
        l.append((i,l2.pop()))
    return l
    
class Consult(webapp.RequestHandler):
    def get(self):
        temp = self.request.get("l",default_value="udes14cegep")
        lines = db.GqlQuery(u"SELECT * FROM Line WHERE code = '"+ temp + u"' LIMIT 1")
        for l in lines :
            nexts = [ nextOne(timePeriod(l),l.tz) ]
            buf = nexts[0]
            for i in [1,2,3,4,5,6] :
                try : 
                    nexts = nexts + [ nextOneTime(timePeriod(l),buf) ]
                    buf = nexts [-1]
                except IndexError:
                    nexts = nexts + [""]
            template_values = {
                'title': "Prochain Passage - "+ l.network + " ligne " + l.line,
                'l' : l,
                'next' : prettyPrintTime(nexts[0]),
                'n1' : prettyPrintTime(nexts[1]),
                'n2' : prettyPrintTime(nexts[2]),
                'n3' : prettyPrintTime(nexts[3]),
                'n4' : prettyPrintTime(nexts[4]),
                'n5' : prettyPrintTime(nexts[5]),
                'n6' : prettyPrintTime(nexts[6])
                }
            path = os.path.join(os.path.dirname(__file__), 'passage.html')
            self.response.out.write(template.render(path, template_values))


class Network(webapp.RequestHandler):
    def get(self):
        cpt = 0
        temp = self.request.get("n",default_value="Sherbrooke")
        alllines = db.GqlQuery("SELECT * FROM Line WHERE network = '"+temp+"' ORDER BY stop ASC, line ASC, direction ASC ")
        content = u""
        for l in alllines:
            if cpt == 0:
                content = ""
                currentStop = l.stop
                currentNetwork = l.network
            if currentNetwork != l.network or cpt == 0 :
                currentNetwork = l.network
                content += '<h3 class="pure">'+currentNetwork+"</h3>"
            if currentStop != l.stop or cpt == 0 :
                currentStop = l.stop
                content += "<h4>"+currentStop+"</h4>"               
            content += '<a class="pure" style="background-color: #'+l.color+';" href="/l/?l='+l.code+'">'+ l.line + " - "+ l.direction +'</a><br />'    
            cpt = cpt + 1
            
        template_values = {
            'title': "Prochain Passage - "+currentNetwork,
            'content' : content,
            }
        path = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(path, template_values))

class Static(webapp.RequestHandler):
    def get(self):
        cpt = 0
        content = ""
        alllines = db.GqlQuery("SELECT * FROM Line ORDER BY network ASC")
        for l in alllines:
            if cpt == 0:
                content = u'<section style="text-align:justify;width:500px;">\n<p> Prochain passage est une application web qui vous donne en un coup d\'oeil les horaires des prochains passage de votre bus / train / tram / RER / Métro etc. Elle fonctionne également sur les navigateur mobiles Android / iOS / WebOS et Blackberry<br /><br />\nL\'application est également disponible via Google Talk : ajoutez le robot <em>prochain-passage@appspot.com</em> à vos contacts !\n</p>\n</section>'  
                currentNetwork = l.network
            if currentNetwork != l.network or cpt == 0 :
                currentNetwork = l.network
                content += '<h3><a class="pure" href="/n/?n='+currentNetwork+'">'+currentNetwork+"</a></h3>"            
            cpt = cpt + 1
            
        template_values = {
            'title': "Prochain Passage",
            'content' : content,
            }
        path = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(path, template_values))

class XMPPHandler(webapp.RequestHandler):

    def help(self):
        message = "Syntaxe incorrecte\n\n"
        message = message + "-l code_ligne pour afficher le prochain passage d'une ligne.\n\n"
        message = message + "-n code_réseau pour afficher les lignes d'un réseau.\n"    
        return message
        
    def rainbow(self,message):
        message.reply("Whoa, that's a full rainbow all the way \n")
        message.reply("Double rainbow, oh my God, double rainbow\n")
        message.reply("It's a double rainbow all the way...damn \n")
        message.reply("It's a double rainbow all the way...damn, oh my God\n")
        message.reply("What does this mean? It's so bright, so vivid\n")
        message.reply("Double rainbow, double rainbow, it's so intense\n")
        message.reply("What does this mean? It's startin to even look like a triple rainbow\n")
        message.reply("That's a whole rainbow, man, ahhhh!\n")
        message.reply("Double rainbow all the way 'cross the sky\n")
        message.reply("Yeah, Yeeeeaaaaah, so intense\n")
        message.reply("Double rainbow all the way 'cross the sky\n")
        message.reply("Wow, wow, oh my God, look at that rainbow\n\n")
        return "http://www.youtube.com/watch?v=MX0D4oZwCsA"
        
    def post(self):
        message = xmpp.Message(self.request.POST)
        # if it is a command
        messageB = message.body
        if messageB[0] == '-' :
            if messageB[0:2] == '-l' :
                request = messageB[3:]
                answer = "Code de ligne inconnu."
                lines = db.GqlQuery(u"SELECT * FROM Line WHERE code = '"+ request + u"' LIMIT 1")     
                for l in lines :       
                    next = nextOne(timePeriod(l),l.tz) 
                    answer = l.network +" - Ligne "+ l.line +"\n"+ l.stop +" vers "+ l.direction+"\n"+prettyPrintTime(next)
            elif messageB[0:2] == '-n' :
                request = messageB[3:]
                answer = u""
                lines = db.GqlQuery(u"SELECT * FROM Line WHERE network = '"+ request + u"'")     
                for l in lines :
                    next = nextOne(timePeriod(l),l.tz) 
                    answer = answer + l.network +" - Ligne "+ l.line +"\n"+ l.stop +" vers "+ l.direction+", code : "+ l.code +"\n"
                if answer == u"" :
                   answer = u"Réseau inconnu."
            else :
                answer = self.help()    
        elif messageB.lower()=="rainbow" : 
              answer = self.rainbow(message)
        elif messageB.lower()=="lolita13ans" : 
              answer = "Coucou ! Tu veux voir ma bite ?"
        else : # displays help   
            answer = self.help()    
        message.reply(answer)
        
        
application = webapp.WSGIApplication(
                                     [('/', Static),
                                      ('/l/', Consult),
                                      ('/n/', Network),
                                      ('/_ah/xmpp/message/chat/', XMPPHandler)],
                                     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
